
#pragma once

#include <vector>
#include "OgreMath/OgreVector3.h"
#include "OgreMath/OgreColourValue.h"
#include "OgreMath/OgreMatrix4.h"
#include "Material.h"
#include "Mesh.h"
#include "Ray.h"
#include "Surfaces.h"
#include "boost/thread.hpp"

class Light
{
public:
	Light(const Ogre::Vector3 _position, const Ogre::ColourValue &_diffuse, const Ogre::ColourValue &_specular)
		: position(_position), diffuse(_diffuse), specular(_specular) {}
	Ogre::Vector3 position;
	Ogre::ColourValue diffuse;
	Ogre::ColourValue specular;

	mutable Ogre::Vector3 positionViewSpace;
	inline void applyModelView(const Ogre::Matrix4 &modelViewMatrix) const
	{
		positionViewSpace = modelViewMatrix * position;
	}
};

struct Scene
{
	~Scene()
	{
		for (auto i = spheres.begin(); i != spheres.end(); i++) delete *i;
		for (auto i = lights.begin(); i != lights.end(); i++) delete *i;
		for (auto i = meshes.begin(); i != meshes.end(); i++) delete *i;
	}
	//lights illuminating the scene
	std::vector<Light*> lights;

	//spheres
	std::vector<Sphere*> spheres;

	//meshes
	std::vector<TransformedMesh*> meshes;

	Ogre::ColourValue backgroundColor;

	void applyViewTransform(const Ogre::Matrix4 &cameraMatrix) const
	{
		for (auto i = spheres.begin(); i != spheres.end(); i++)
			(*i)->applyModelView(cameraMatrix);

		for (auto i = lights.begin(); i != lights.end(); i++)
			(*i)->applyModelView(cameraMatrix);

		for (auto i = meshes.begin(); i != meshes.end(); i++)
			(*i)->applyModelView(cameraMatrix);
	}
};